﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
using System.Web;
using Utility;

namespace DataAccess
{
    public class OperationDA : BaseDA
    {
        //private OperationDA() { }

        public static OperationDA Instance
        {
            get
            {
                return new OperationDA();
            }
        }

        public DataSet GetList(string procName, IDictionary<string, object> queryParams)
        {
            SetTimeout(queryParams);
            return Query(procName, queryParams);
        }

        /// <summary>
        /// 读取文本，获取数据
        /// </summary>
        /// <param name="asText"></param>
        /// <param name="queryParams"></param>
        /// <returns></returns>
        /// <example>
        ///  {@p参数 或者 @pp参数}-- 无参数自动消除，@pp参数直接在文本上替换，可以用于动态排序 @@pORDERBY
        /// </example>
        public DataSet QueryAsText(string asText, IDictionary<string, object> queryParams)
        {
            if (asText.Trim().StartsWith("@"))
            {
                string filename = asText.Trim().Substring(1).ToUpper();
                if (HttpRuntime.Cache["SQLTEXT_CACHE"] != null)
                {
                    Dictionary<string, string> dictSqlText = (Dictionary<string, string>)HttpRuntime.Cache["SQLTEXT_CACHE"];
                    if (dictSqlText.ContainsKey(filename))
                    {
                        asText = dictSqlText[filename];
                    }
                    else
                    {
                        string filePath = Path.Combine(HttpContext.Current.Server.MapPath("~"), "SqlText", filename + ".SQL");
                        asText = File.ReadAllText(filePath, System.Text.Encoding.UTF8);
                        dictSqlText[filename] = asText;
                    }
                    
                }
                else
                {
                    string filePath = Path.Combine(HttpContext.Current.Server.MapPath("~"), "SqlText", filename + ".SQL");
                    asText = File.ReadAllText(filePath, System.Text.Encoding.UTF8);
                    Dictionary<string, string> dictSqlText = new Dictionary<string, string>();
                    dictSqlText[filename] = asText;
                    HttpRuntime.Cache.Insert("SQLTEXT_CACHE", dictSqlText, null, DateTime.Now.AddDays(1), System.Web.Caching.Cache.NoSlidingExpiration);
                }
            }

            asText = ExecuteEvalSqlCode(asText, queryParams);

            SetTimeout(queryParams);
            return QueryTextByParams(asText, queryParams);
        }

        public string ExecuteEvalSqlCode(string sourceCode, IDictionary<string, object> queryParams)
        {
            string regFindAph = @"@p(\w+)|@@p(\w +)";
            string regFind1 = @"\{[\s\S]*?\}";
            MatchCollection ms = Regex.Matches(sourceCode, regFind1);
            foreach (Match m in ms)
            {
                if (!m.Success)
                {
                    continue;
                }
                string wholeString = m.Groups[0].Value;

                Match matchArgument = Regex.Match(wholeString, regFindAph);
                if (matchArgument.Success)
                {
                    string paramName = matchArgument.Groups[1].Value;
                    if (!queryParams.ContainsKey(paramName))
                    {
                        sourceCode = sourceCode.Replace(wholeString, "");
                    }
                    else
                    {
                        sourceCode = sourceCode.Replace(wholeString, wholeString.Trim().Trim('}', '{'));
                    }
                }
            }

            string regReplace = @"@@p(\w+)";
            ms = Regex.Matches(sourceCode, regReplace);
            foreach (Match m in ms) {
                if (!m.Success)
                {
                    continue;
                }

                string wholeString = m.Groups[0].Value;
                string paramName = m.Groups[1].Value;
                if (queryParams.ContainsKey(paramName))
                {
                    string replaceValue = queryParams[paramName].ToString();
                    sourceCode = sourceCode.Replace(wholeString, replaceValue);
                }
            }

            return sourceCode;
        }

        public IDictionary<string, object> Operation(string procName, IDictionary<string, object> queryParams)
        {
            SetTimeout(queryParams);
            return ExcuteOutput(procName, queryParams);
        }

        public IDictionary<string, object> ExecuteTransate(List<IDictionary<string, object>> transParams)
        {
            List<IDictionary<string, object>> details = transParams;
            IDictionary<string, object> result = null;
            Dictionary<string, object> markAssmbly = new Dictionary<string, object>();
            if (details.Count == 0) {
                Logger.Instance.WriteEventLog("批量事务提交", "ExecuteTransate", new Dictionary<string, object>(), new Exception("提交明细为空"));
                return null;
            }
                
            string db_name = details[0]["DB_NAME"].ToString();
            IDictionary<string, object> getDbNameParams = new Dictionary<string, object>();
            getDbNameParams["DB_NAME"] = db_name;

            string each_span_name = "";
            IDictionary<string, object> each_paramsValue = null;

            using (DbConnection conn = OperationDA.Instance.GetCurrentDB(getDbNameParams).CreateConnection())
            {
                if (conn.State != System.Data.ConnectionState.Open)
                {
                    conn.Open();
                }
                using (DbTransaction trans = conn.BeginTransaction())
                {
                    try
                    {
                        OperationDA da = OperationDA.Instance;
                        da.JoinTrans = trans;
                        foreach (IDictionary<string, object> detail in details)
                        {
                            IDictionary<string, object> normal = detail;
                            normal["DB_NAME"] = db_name;
                            each_paramsValue = normal;

                            if (detail.ContainsKey("SP_NAME"))
                            {
                                each_span_name = detail["SP_NAME"].ToString();
                            }
                            else if(detail.ContainsKey("TB_NAME")){
                                each_span_name = "SP_" + detail["TB_NAME"].ToString() + "_" + detail["m"].ToString();
                            }
                           
                            Dictionary<string, object> dicParamsChange = new Dictionary<string, object>();

                            foreach (KeyValuePair<string, object> pairExistAt in normal)
                            {
                                Match m = Regex.Match(pairExistAt.Value.ToString(), @"^\s*\$@\$(\w+):?(\w*)");

                                if (m.Success)
                                {
                                    string existAt = m.Groups[1].Value;
                                    string direct_sp_name = "";
                                    if (m.Groups.Count > 2)
                                    {
                                        direct_sp_name = m.Groups[2].Value;
                                    }
                                    foreach (KeyValuePair<string, object> pairMark in markAssmbly)
                                    {
                                        if (pairMark.Key == each_span_name)
                                            continue;
                                        if (!string.IsNullOrWhiteSpace(direct_sp_name) && direct_sp_name != pairMark.Key)
                                        {
                                            continue;
                                        }
                                        IDictionary<string, object> markDic = (IDictionary<string, object>)pairMark.Value;
                                        if (markDic.ContainsKey(existAt))
                                        {
                                            dicParamsChange[pairExistAt.Key] = markDic[existAt];
                                            break;
                                        }
                                    }
                                }
                            }
                            if (dicParamsChange.Keys.Count > 0)
                            {
                                foreach (KeyValuePair<string, object> pairChange in dicParamsChange)
                                {
                                    normal[pairChange.Key] = pairChange.Value;
                                }
                            }

                            if (each_span_name.ToUpper() == "HTML2PDF")
                            {
                                result = new Dictionary<string, object>();
                                string arguments = "";
                                foreach (KeyValuePair<string, object> arg in normal)
                                {
                                    if (arg.Key == "TB_NAME" || arg.Key == "DB_NAME" || arg.Key == "SP_NAME")
                                    {
                                        continue;
                                    }
                                    arguments += string.Format("\\{0}:[{1}] ", arg.Key, arg.Value);
                                }

                                string cmd = Path.Combine(System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "html2pdf", "HTML2PDFConsole.exe");
                                if (!File.Exists(cmd))
                                {
                                    result["RETURN_CODE"] = "98";
                                    result["RETURN_MESSAGE"] = "[在线]生成PDF出错";
                                }
                                else
                                {
                                    ProcessStartInfo psi = new ProcessStartInfo();
                                    psi.FileName = cmd;
                                    psi.Arguments = arguments;
                                    psi.UseShellExecute = false;
                                    psi.RedirectStandardInput = false;
                                    psi.RedirectStandardOutput = true;
                                    psi.CreateNoWindow = true;
                                    Process pinfo = Process.Start(psi);
                                    pinfo.WaitForExit();

                                    if (pinfo.ExitCode == 0)
                                    {
                                        string path = pinfo.StandardOutput.ReadToEnd();

                                        result["HTML2PDF_PATH"] = (System.Configuration.ConfigurationManager.AppSettings["HTTP_PATH"] + path).Replace("\\", "/");
                                        result["RETURN_CODE"] = "0";
                                        pinfo.StandardOutput.Close();
                                    }
                                    else
                                    {
                                        result["RETURN_CODE"] = "99";
                                        result["RETURN_MESSAGE"] = "[在线]生成PDF出错";
                                    }
                                }
                            }
                            else if (each_span_name.ToUpper() == "CRYSTAL_REPORT")
                            {
                                result = new Dictionary<string, object>();
                                string rpt_save_filename = CrystalReport(normal);
                                result["RPT_SAVE_FILENAME"] = rpt_save_filename;
                                if (!string.IsNullOrEmpty(rpt_save_filename))
                                {
                                    result["RETURN_CODE"] = "0";
                                    result["RETURN_MESSAGE"] = "报表生成成功";
                                }
                                else
                                {
                                    result["RETURN_CODE"] = "99";
                                    result["RETURN_MESSAGE"] = "报表生成失败";
                                }
                            }
                            else if (each_span_name.ToUpper() == "SEND_SMS")
                            {
                                result = SendSMS(normal);
                            }
                            else
                            {
                                try
                                {
                                    result = da.ExcuteOutput(each_span_name, normal);

                                }
                                catch(Exception)
                                {
                                    result = new Dictionary<string, object>();
                                    result["RETURN_CODE"] = "99";
                                    result["RETURN_MESSAGE"] = "执行数据库失败，请联系管理员";
                                    throw;
                                }
                            }

                            markAssmbly[each_span_name] = result;

                            if (result["RETURN_CODE"].ToString() != "0")
                            {
                                Exception _ex = new Exception(result["RETURN_MESSAGE"].ToString());
                            
                                Logger.Instance.WriteEventLog("DML操作 异常", "ExecuteTransate", (Dictionary<string, object>)normal, _ex, LoggerType.sql);
                                throw new Exception(result["RETURN_MESSAGE"].ToString());
                            }
                        }

                        trans.Commit();
                    }
                    catch (Exception ex)
                    {
                        Logger.Instance.WriteEventLog("DML操作 异常", "ExecuteTransate","", ex, "", LoggerType.sql);
                        trans.Rollback();
                    }
                }
            }

            return result;
        }

        private IDictionary<string, object> SendSMS(IDictionary<string, object> normal)
        {
            SMS_ZHIQING_Help sms = new SMS_ZHIQING_Help();
            string content = normal["TEMPLATE_TEXT"].ToString();
            foreach (string key in normal.Keys)
            {
                string replace = normal[key].ToString();
                if (key == "SCHEDULE_DATE_FROM" && normal[key] is DateTime)
                {
                    replace = string.Format("{0:yyyy年MM月dd日 HH:mm ddd}", normal[key]);
                }
                content = content.Replace("{" + key + "}", replace);
            }
            //   normal["TEMPLATE_TEXT"] = content;
            string phone = normal["PHONE"].ToString();
            if (string.IsNullOrEmpty(phone))
            {
                phone = "";
            }
            string sms_modlue = normal["enableSMS_SCHEDULE"].ToString();

            return sms.SendMessage(sms_modlue, content, new string[] { phone });
        }

        public string CrystalReport(IDictionary<string, object> formParams)
        {
            try
            {
                string server = ConfigurationManager.AppSettings["RPT_SERVER"];
                string database = ConfigurationManager.AppSettings["RPT_DATABASE"];
                string user = ConfigurationManager.AppSettings["RPT_USER"];
                string password = ConfigurationManager.AppSettings["RPT_PASSWORD"];
                string rptFilename = formParams["RPT_SOURCE_FILENAME"].ToString();
                string rptSaveFileName = formParams["RPT_SAVE_FILENAME"].ToString();
                string type = formParams["RPT_TYPE"].ToString();
                bool isCover = true;
                if (formParams["RPT_ISCOVER"] is bool)
                {
                    isCover = (bool)formParams["RPT_ISCOVER"];
                }
                string ref_key = formParams["RPT_REF_KEYS"].ToString();

                CrystalReportHelper.Instance.ExportToDisk(formParams, rptFilename, rptSaveFileName, type, server, database, user, password, isCover, ref_key.Split(','));

                CrystalReportHelper.outputFullPath = CrystalReportHelper.outputFullPath.Replace(CrystalReportHelper.Instance.GetPath(), ConfigurationManager.AppSettings["HTTP_PATH"]);
                return CrystalReportHelper.outputFullPath;
            }
            catch (Exception ex)
            {
                ErrorLog.Instance.WriteWCFError("MaloClinicsService", "CrystalReport", "", formParams, ex);
                EmailHelper.Instance.SendMail(string.Format("{0}[{1}]", ConfigurationManager.AppSettings["SERVER"], "水晶报表执行错误"), ex.Message);
                return "";
            }
        }

        void SetTimeout(IDictionary<string, object> formParams)
        {
            int _timeOut = -1;
            if (formParams.Keys.Contains("pto"))
            {
                _timeOut = int.Parse(formParams["pto"].ToString());
            }

            if (_timeOut > 0)
            {
                this.TimeOut = _timeOut;
            }
        }
    }
}